/**
 * <copyright>
 * Copyrigth 2007 Aurelien Moreau
 *
 * This file is part of ProcessShop.
 *
 * ProcessShop is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * ProcessShop is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with ProcessShop; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 * </copyright>
 *
 * $Id$
 */
package net.yienyien.process.folder.impl;

import java.util.ArrayList;

import net.yienyien.process.bpd.BPDModel;
import net.yienyien.process.bpd.BPDObject;
import net.yienyien.process.folder.BPDFoldListener;
import net.yienyien.process.folder.BPDFolder;
import net.yienyien.process.folder.artifacts.BPDPattern;
import net.yienyien.process.folder.artifacts.PatternedBPDComponent;
import net.yienyien.process.folder.componentizer.BPDComponentizer;
import net.yienyien.process.folder.componentizer.BPDComponentizerFactory;

import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;

public class BPDFolderImpl implements BPDFoldListener, BPDFolder {
	private BPDComponentizer componentizer;
	
	private ArrayList<BPDFoldListener> listeners;
	
	public BPDFolderImpl() {
		componentizer=BPDComponentizerFactory.INSTANCE.newComponentizer();
		listeners=new ArrayList<BPDFoldListener>();
	}
		

	@Override
	public void addPattern(BPDPattern pattern) {
		componentizer.addPattern(pattern);
	}	

	@Override
	public void removePattern(BPDPattern pattern) {
		componentizer.removePattern(pattern);
	}
	
	private boolean isInclude(BPDModel model, EList<BPDObject> activeObjects) {
		for(BPDObject o: activeObjects) {
			if(!model.getObjects().contains(o)) {
				return false;
			}
		}
		return true;
	}
	
	/* (non-Javadoc)
	 * @see net.yienyien.process2bpel.reduction.BPDFolder#loopFold(net.yienyien.process2bpel.bpd.BPDModel)
	 */
	public void loopFold(BPDModel model) {
		EList<BPDObject> objects=new BasicEList<BPDObject>();
		objects.addAll(model.getObjects());
		loopFold(model, objects);
	}
	
	/* (non-Javadoc)
	 * @see net.yienyien.process2bpel.reduction.BPDFolder#loopFold(net.yienyien.process2bpel.bpd.BPDModel, java.util.Collection)
	 */
	public void loopFold(BPDModel model, EList<BPDObject> activeObjects) {		
		while(activeObjects.size()>3) {
			if(!fold(model, activeObjects)) {
				return;
			}
		}
	}
	
	/* (non-Javadoc)
	 * @see net.yienyien.process2bpel.reduction.BPDFolder#fold(net.yienyien.process2bpel.bpd.BPDModel, java.util.Collection)
	 */
	public boolean fold(BPDModel model, EList<BPDObject> activeObjects) {
		assert(isInclude(model, activeObjects));
		
		boolean cont=true;
		pre(model); // PRE
		
		{ // FOLD
			PatternedBPDComponent m=componentizer.findComponent(activeObjects);
			if(m!=null) {
				fold(model, m);
				activeObjects.removeAll(m.getObjects());
				activeObjects.add(m);
				model.fold(m);
			} else {
				cont=false;
			}
		} // END FOLD

		post(model); // POST
		return cont;
	}

	@Override
	public void pre(BPDModel model) {
		for(BPDFoldListener l: listeners) {
			l.pre(model);
		}
	}
	
	@Override
	public void fold(BPDModel model, PatternedBPDComponent pcomp) {
		for(BPDFoldListener l: listeners) {
			l.fold(model, pcomp);
		}
	}

	@Override
	public void post(BPDModel model) {
		for(BPDFoldListener l: listeners) {
			l.post(model);
		}	
	}


	@Override
	public void addListener(BPDFoldListener listener) {
		listeners.add(listener);
	}


	@Override
	public void removeListener(BPDFoldListener listener) {
		listeners.remove(listener);
	}


	@Override
	public String getName() {
		return null;
	}


}
